﻿namespace DJLang
{
    public static class DJConvertExt
    {
        public static DJInt ToInt(this IDJValue v) => v switch
        {
            DJBasic<bool> b => new(b.val ? 1 : 0),
            DJBasic<int> i => new(i.val),
            DJBasic<float> f => new((int)f.val),
            DJRef<string> s => int.TryParse(s.val, out int i) ? new(i) : null,
            _ => new(default)
        };

        public static DJFloat ToFloat(this IDJValue v) => v switch
        {
            DJBasic<int> i => new(i.val),
            DJBasic<float> f => new(f.val),
            DJRef<string> s => float.TryParse(s.val, out float f) ? new(f) : null,
            _ => new(default)
        };

        public static DJRef<string> ToString(this IDJValue v) => v switch
        {
            DJBasic<bool> b => new($"{b.val}"),
            DJBasic<int> i => new($"{i.val}"),
            DJBasic<float> f => new($"{f.val}"),
            DJRef<string> s => s,
            _ => new($"{v}")
        };

        public static T As<T>(this IDJValue v) where T : class, IDJValue
        {
            return v is T t ? t : null;
        }

        public static DJBasic<T> AsBasic<T>(this IDJValue v) where T : struct
        {
            return (DJBasic<T>)v;
        }

        public static DJRef<T> AsRef<T>(this IDJValue v) where T : class
        {
            return (DJRef<T>)v;
        }

        public static T GetValue<T>(this IDJValue v) where T : struct
        {
            return v.AsBasic<T>().val;
        }

        public static T GetValueOr<T>(this IDJValue v, T d) where T : struct
        {
            if (v is DJBasic<T> b) return b.val;
            return d;
        }

        public static T GetManaged<T>(this IDJValue v) where T : class
        {
            return v.AsRef<T>().val;
        }
    }
}
